/********************************************
 * 功能说明: Web端TenantEmployee基础业务控制器
 * 模块名称:
 * 系统名称:
 * 软件版权: Frank
 * 系统版本: 1.0.0.1
 * 开发人员:
 * 开发时间: 2019-12-18 18:41:08
 * 审核人员:
 * 相关文档:
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.spring.arch.uaa.web.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.codahale.metrics.annotation.Timed;
import com.spring.arch.common.dto.result.PageResultDTO;
import com.spring.arch.common.dto.result.ResultDTO;
import com.spring.arch.common.security.CurrentUserContextHolder;
import com.spring.arch.common.security.UserPrincipal;
import com.spring.arch.uaa.errorcode.UaaErrorCode;
import com.spring.arch.uaa.web.dto.WebTenantEmployeeDTO;
import com.spring.arch.common.dto.result.PageResultDTO;
import com.spring.arch.common.dto.result.ResultDTO;
import com.spring.arch.common.exception.ExceptionHolder;
import com.spring.arch.common.security.CurrentUserContextHolder;
import com.spring.arch.common.security.UserPrincipal;
import com.spring.arch.uaa.errorcode.UaaErrorCode;
import com.spring.arch.uaa.excel.OrganizationImportBean;
import com.spring.arch.uaa.excel.TenantEmployeeExportBean;
import com.spring.arch.uaa.excel.TenantEmployeeImportBean;
import com.spring.arch.uaa.excel.TenantEmployeeListener;
import com.spring.arch.uaa.model.Project;
import com.spring.arch.uaa.model.TenantEmployee;
import com.spring.arch.uaa.repository.*;
import com.spring.arch.uaa.repository.custom.UaaRepository;
import com.spring.arch.uaa.service.TenantEmployeeService;
import com.spring.arch.uaa.web.converter.WebTenantEmployeeConverter;
import com.spring.arch.uaa.web.dto.WebTenantEmployeeDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.UUID;


/**
 * Web端TenantEmployee基础业务控制器
 *
 * @author
 * @version 1.0.0.1
 * @since 2019-12-18 18:41:08
 */
@Slf4j
@RestController
@RequestMapping(value = "/uaa/w/tenantEmployee", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(tags = {"Web端TenantEmployee管理API"})
public class WebTenantEmployeeController {

    @Autowired
    private UaaRepository uaaRepository;

    @Autowired
    private TenantRepository tenantRepository;

    @Autowired
    private OrganizationRepository organizationRepository;

    @Autowired
    private TenantEmployeeService tenantEmployeeService;

    @Autowired
    private TenantEmployeeRepository tenantEmployeeRepository;

    @Autowired
    private WebTenantEmployeeConverter tenantEmployeeConverter;

    @Autowired
    private OrganizationEmployeeRepository organizationEmployeeRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ProjectRepository projectRepository;

    /**
     * 新建操作
     *
     * @param tenantEmployeeDTO 新建资源的DTO
     * @return 新建资源
     */
    @Timed
    @ApiOperation(value = "新建操作")
    @PostMapping
    public ResultDTO<WebTenantEmployeeDTO> create(
            @RequestHeader(value = "clientId", required = false) UUID projectId,
            @RequestBody @Valid final WebTenantEmployeeDTO tenantEmployeeDTO) {

        Optional<Project> optionalProject = projectRepository.findById(projectId);
        if(!optionalProject.isPresent()) {
            projectId = null;
        }
        final TenantEmployee model = this.tenantEmployeeConverter.toModel(tenantEmployeeDTO);
        this.tenantEmployeeService.save(model, projectId);
        if(log.isInfoEnabled()) {
            log.info("{} instance {} was created.", TenantEmployee.class.getSimpleName(), model.getId());
        }
        return this.tenantEmployeeConverter.toResultDTO(model);
    }

    /**
     * 删除操作
     *
     * @param id 实体对象ID
     * @return 操作结果
     */
    @Timed
    @ApiOperation(value = "删除操作")
    @DeleteMapping(value = "/{id}")
    public ResultDTO<Void> delete(@PathVariable final UUID id) {
        this.tenantEmployeeService.deleteById(id);
        if(log.isInfoEnabled()) {
            log.info("{} instance {} was disable.", TenantEmployee.class.getSimpleName(), id);
        }
        return ResultDTO.success();
    }

    /**
     * 更新操作
     *
     * @param id                实体对象ID
     * @param tenantEmployeeDTO 更新资源的DTO
     * @return 更新后资源
     */
    @Timed
    @ApiOperation(value = "更新操作")
    @PutMapping(value = "/{id}")
    public ResultDTO<WebTenantEmployeeDTO> update(@PathVariable final UUID id,
                                                  @RequestBody @Valid final WebTenantEmployeeDTO tenantEmployeeDTO) {
        tenantEmployeeDTO.setId(id);
        final TenantEmployee model = this.tenantEmployeeConverter.toModel(tenantEmployeeDTO);
        this.tenantEmployeeService.save(model, null);
        if(log.isInfoEnabled()) {
            log.info("{} instance {} was updated.", TenantEmployee.class.getSimpleName(), model.getId());
        }
        return this.tenantEmployeeConverter.toResultDTO(model);
    }

    /**
     * 获取分页数据
     *
     * @param pageable 分页+排序参数
     * @return 分页数据
     */
    @Timed
    @ApiOperation(value = "获取分页数据")
    @PostMapping(value = "/s")
    public PageResultDTO<WebTenantEmployeeDTO> search(
            @RequestHeader(value = "clientId", required = false) UUID projectId,
            @PageableDefault(sort = {"createdDate"}, direction = Sort.Direction.DESC) final Pageable pageable,
            @RequestParam(value = "code", required = false) String code,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "mobile", required = false) String mobile,
            @RequestParam(value = "status", required = false) Boolean status) {

        UserPrincipal user = CurrentUserContextHolder.getCurrentUser();

        Optional<Project> optionalProject = projectRepository.findById(projectId);
        if(!optionalProject.isPresent()) {
            projectId = null;
        }

        Page<TenantEmployee> page = uaaRepository.searchEmploy(user.getTenantId(), projectId, code, name,
                mobile, status, pageable);

        return this.tenantEmployeeConverter.toResultDTO(page);
    }

    /**
     * 取得详细数据
     *
     * @param id 实体对象ID
     * @return 资源详细
     */
    @Timed
    @ApiOperation(value = "获取详细数据")
    @GetMapping(value = "/{id}")
    public ResultDTO<WebTenantEmployeeDTO> get(@PathVariable final UUID id) {
        final TenantEmployee model = this.tenantEmployeeRepository.findById(id)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001001002, id.toString()));
        return this.tenantEmployeeConverter.toResultDTO(model);
    }

    /**
     * 获取下拉列表分页数据
     *
     * @param pageable 分页+排序参数
     * @return 分页数据
     */
    @Timed
    @ApiOperation(value = "获取下拉列表分页数据")
    @PostMapping(value = "/list")
    public PageResultDTO<WebTenantEmployeeDTO> searchList(
            @PageableDefault(value = 10, sort = {"createdDate"}, direction = Sort.Direction.DESC) final Pageable pageable,
            @RequestParam("value") String value) {

        UserPrincipal user = CurrentUserContextHolder.getCurrentUser();

        Page<TenantEmployee> page = uaaRepository.searchEmployForList(user.getTenantId(), user.getProjectId(), value,
                pageable);

        return this.tenantEmployeeConverter.toResultDTO(page);
    }

    /**
     * 下载模板
     */
    @Timed
    @ApiOperation(value = "下载模板")
    @PostMapping(value = "/export/template")
    public void exportTemplate(HttpServletResponse response) {

        long st = System.currentTimeMillis();
        try {
            response.reset();
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("import.xlsx", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);

            ExcelWriter excelWriter = EasyExcelFactory.getWriter(response.getOutputStream());
            WriteSheet tenantEmployee = EasyExcel.writerSheet(1, "人员导入").head(TenantEmployeeImportBean.class).build();
            excelWriter.write(Arrays.asList(new TenantEmployeeImportBean()), tenantEmployee);

            WriteSheet organization = EasyExcel.writerSheet(2, "组织架构管理").head(OrganizationImportBean.class).build();
            excelWriter.write(Arrays.asList(new OrganizationImportBean()), organization);

            excelWriter.finish();

        } catch (IOException e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            log.error("WebTenantEmployeeController:/export: error", e);
            ResultDTO.failure("导出出错，请检查！");
        } finally {
            long et = System.currentTimeMillis();
            log.debug("WebTenantEmployeeController:/export 导出成功, 耗时：" + (et - st));
        }
    }

    /**
     * 导入人员数据
     */
    @Timed
    @ApiOperation(value = "导入人员数据")
    @PostMapping(value = "/import")
    public void importData(@RequestParam("file") MultipartFile file, @ApiIgnore HttpServletResponse response) {

        long st = System.currentTimeMillis();
        TenantEmployeeListener tenantEmployeeListener = new TenantEmployeeListener();

        tenantEmployeeListener.setTenantEmployeeRepository(tenantEmployeeRepository);
        tenantEmployeeListener.setUserRepository(userRepository);
        tenantEmployeeListener.setOrganizationRepository(organizationRepository);
        tenantEmployeeListener.setOrganizationEmployeeRepository(organizationEmployeeRepository);
        tenantEmployeeListener.setTenant(tenantRepository.findById(CurrentUserContextHolder.getCurrentUser().getTenantId()).get());
        Project project = projectRepository.findById(CurrentUserContextHolder.getCurrentUser().getProjectId()).get();
        tenantEmployeeListener.setRootOrganization(project.getRootOrganization());
        tenantEmployeeListener.setProject(project);

        try {

            ExcelReader excelReader = EasyExcelFactory.read(file.getInputStream()).build();
            ReadSheet tenantEmployeeSheet = EasyExcel.readSheet("用户数据").head(TenantEmployeeExportBean.class)
                    .registerReadListener(tenantEmployeeListener).build();
            excelReader.read(tenantEmployeeSheet);
            excelReader.finish();

            List<TenantEmployeeExportBean> tenantEmployeeExportBeans = tenantEmployeeListener.getList();

            response.reset();
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("importResult.xlsx", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);

            EasyExcel.write(response.getOutputStream(), TenantEmployeeExportBean.class).sheet("用户数据").doWrite(tenantEmployeeExportBeans);

        } catch (IOException e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            log.error("WebTenantEmployeeController:/export: error", e);
            ResultDTO.failure("导出出错，请检查！");
        } finally {
            long et = System.currentTimeMillis();
            log.debug("WebTenantEmployeeController:/export 导出成功, 耗时：" + (et - st));
        }
    }
}
